home *** CD-ROM | disk | FTP | other *** search
- Path: grimsel.zurich.ibm.com!usenet
- From: Keith Whittingham <wgk@zurich.ibm.com>
- Newsgroups: comp.lang.c++
- Subject: 'chained': It would be nice if...
- Date: Wed, 17 Apr 1996 15:17:16 -0700
- Organization: IBM Zurich Research Laboratory
- Message-ID: <31756DEC.5215@zurich.ibm.com>
- NNTP-Posting-Host: pine.zurich.ibm.com
- Mime-Version: 1.0
- Content-Type: text/plain; charset=us-ascii
- Content-Transfer-Encoding: 7bit
- X-Mailer: Mozilla 2.01 (Win16; I)
-
- Three or four times I've find myself needing a construct which I
- think is missing from C++ (or at least is inaccessable).
-
- A keyword, say 'chained', to have a similar effect to that of
- the virtual destructor. e.g.
-
- class Base
- {
- public:
- virtual void vMember(void);
- chained void cMember(void);
- };
-
- class Derived:
- public Base
- {
- public:
- void vMember(void);
- void cMember(void);
- };
-
- Calling Derived::vMember() executes the code contained in the body
- Derived::vMember() whereas calling Derived::cMember() would
- execute the code contained in the body Base::cMember() and then
- the code contained in Derived::cMember(). This similar and not
- identical to the chaining in a virtual destructor in as much as
- the child destructor gets called before the parents.
-
- Why? Well mainly to give the class designer the ability to force
- users of his class to call the base function when overriding. This
- is best described with an example:
-
- class Node { /*...*/ };
-
- class Bag
- {
- public:
- Bag() { count = 0; Fic = 0; }
- virtual void Add(Node &n)
- {
- LinkIn(n);
- count++;
- }
- int Count(void) const { return count; }
- void LinkIn(Node &New);
-
- protected:
- int count;
- private:
- Node *Fic; // First in chain
- };
-
-
- class SortedBag:
- public Bag
- {
- public:
- void Add(Node &n)
- {
- LinkIn(n);
- Sort();
- count++; // !! Must do this !!
- }
- void Sort(void);
- };
-
- We can see the code for Add() and we can see that if we were to
- override Add() with, say, SortedBag::Add() that we must ensure
- that count is incremented when the object is added to the bag.
-
- Redefining Add() as 'chained' in the base class Bag
-
- class Node { /*...*/ };
-
- class Bag
- {
- public:
- Bag() { count = 0; Fic = 0; }
- chained void Add(Node &n)
- {
- LinkIn(n);
- count++;
- }
- int Count(void) const { return count; }
- void LinkIn(Node &New);
-
- private:
- int count;
- Node *Fic; // First in chain
- };
-
-
- class SortedBag:
- public Bag
- {
- public:
- void Add(Node &n)
- {
- Sort();
- }
- void Sort(void);
- };
-
- The class designer knows that the semantics of Add() are not lost
- and does not need to advertise the fact that count must be
- incremented if Add() is overriden. There is a second advantage in
- that the member 'count' does not need to be exposed albeit only as
- a protected member.
-
- The real advantage of a chained keyword is to follow, without
- really knowing, the class hierarchy. I recently implemented
- a dynamic_cast type function by using an abstract base class
- with a return ClassType() member in the base class and a
- conversion operator. In order to allow a cast it was necessary
- to traverse the class hierarchy in order to ascertain if indeed
- the object was of the target class type. The only way I found of
- achieving this functionality was to provide a ParentChild()
- macro to be used in each class which defined a function which
- had the semantic "return OK if I am same type as target or
- ask my parent".
-
- Interested to hear what you think or how this might be
- implemented with writing a compiler!
-
-
- --
- Keith Whittingham
- wgk@zurich.ibm.com
-